package sg.edu.nus.iss.vmcs.interfaces;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import sg.edu.nus.iss.vmcs.customer.CustomerUI;
import sg.edu.nus.iss.vmcs.machinery.MachineryController;
import sg.edu.nus.iss.vmcs.machinery.MachineryInterface;
import sg.edu.nus.iss.vmcs.maintenance.MaintenanceController;
import sg.edu.nus.iss.vmcs.maintenance.MaintenanceUI;
import sg.edu.nus.iss.vmcs.system.Environment;
import sg.edu.nus.iss.vmcs.system.MainController;
import sg.edu.nus.iss.vmcs.system.SimulationController;
import sg.edu.nus.iss.vmcs.system.TransactionController;
import sg.edu.nus.iss.vmcs.system.VMCSControlUI;

public abstract class InterfaceFactory {
	public abstract CustomerUI createCustomerUI(TransactionController tc, MainController mc);
	public abstract MaintenanceUI createMaintenanceUI(MaintenanceController controller);
	public abstract MachineryInterface createMachineryInterface(MachineryController controller);
	public abstract VMCSControlUI createVMCSControlUI(SimulationController controller);
	
	private static InterfaceFactory uiFactory = null;
	public static InterfaceFactory getInstance() {
		if (uiFactory == null) {
			String concreteClassName = "";
			try {
				concreteClassName = Environment.getInterfaceFactoryClassName();
				Class<? extends InterfaceFactory> concreteClass = Class.forName(concreteClassName).asSubclass(InterfaceFactory.class);
				Method getInstanceMethod = concreteClass.getMethod("getInstance", new Class[0]);
				uiFactory = ((InterfaceFactory)getInstanceMethod.invoke(null, new Object[0]));
				System.out.println("<<Abstract Factory>> An instance of class '" +concreteClassName+ "' has been obtained.");
			} catch (ClassNotFoundException e) {
				System.out.println("===<<Abstract Factory>>[begin]===============================================================");
				e.printStackTrace();
				System.out.println("===<<Abstract Factory>>[end]===============================================================");
			} catch (IllegalAccessException e) {
				System.out.println("===<<Abstract Factory>>[begin]===============================================================");
				e.printStackTrace();
				System.out.println("===<<Abstract Factory>>[end]===============================================================");
			} catch (IllegalArgumentException e) {
				System.out.println("===<<Abstract Factory>>[begin]===============================================================");
				e.printStackTrace();
				System.out.println("===<<Abstract Factory>>[end]===============================================================");
			} catch (InvocationTargetException e) {
				System.out.println("===<<Abstract Factory>>[begin]===============================================================");
				e.printStackTrace();
				System.out.println("===<<Abstract Factory>>[end]===============================================================");
			} catch (NoSuchMethodException e) {
				System.out.println("===<<Abstract Factory>>[begin]===============================================================");
				e.printStackTrace();
				System.out.println("===<<Abstract Factory>>[end]===============================================================");
			} catch (SecurityException e) {
				System.out.println("===<<Abstract Factory>>[begin]===============================================================");
				e.printStackTrace();
				System.out.println("===<<Abstract Factory>>[end]===============================================================");
			}
			if (uiFactory == null) {
				System.out.print(
						"<<Abstract Factory>> Unable to create an instance of class '" +concreteClassName+ "'.\n" +
						"<<Abstract Factory>> Please make sure that the .class file exists in the CLASSPATH and use the fully qualified class name (including the full package name).\n"
						);
			}
		}
		return uiFactory;
	}
}
